package common.config.http;

import common.config.exception.BaseErrorInfoInterface;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;

import javax.annotation.Nullable;
import javax.servlet.RequestDispatcher;
import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;

/**
 * 状态码
 *
 * @author 米泽鹏
 * @since 2021-07-08 下午 8:05
 */
@Getter
@Slf4j
public enum HttpStatusEnum implements BaseErrorInfoInterface {

	// 状态码定义：

	CONTINUE(100, "继续"),
	SWITCHING_PROTOCOLS(101, "切换协议"),
	PROCESSING(102, "处理中"),
	CHECKPOINT(103, "检查点"),

	SUCCESS(200, "成功"),
	CREATED(201, "已创建"),
	Accepted(202, "已接受"),
	NON_AUTHORITATIVE_INFORMATION(203, "非授权信息"),
	NO_CONTENT(204, "无内容"),
	RESET_CONTENT(205, "重置内容"),
	PARTIAL_CONTENT(206, "部分内容"),
	MULTI_STATUS(207, "多状态"),
	ALREADY_REPORTED(208, "已报告"),
	IM_USED(226, "IM使用"),

	MULTIPLE_CHOICES(300, "多种选择"),
	MOVED_PERMANENTLY(301, "永久移动"),
	FOUND(302, "已找到"),
	@Deprecated
	MOVED_TEMPORARILY(302, "临时移动"),
	SEE_OTHER(303, "查看其它地址"),
	NOT_MODIFIED(304, "未修改"),
	@Deprecated
	USE_PROXY(305, "使用代理"),
	TEMPORARY_REDIRECT(307, "临时重定向"),
	PERMANENT_REDIRECT(308, "永久重定向"),

	BAD_REQUEST(400, "错误请求"),
	UNAUTHORIZED(401, "未授权"),
	PAYMENT_REQUIRED(402, "保留，将来使用"),
	FORBIDDEN(403, "禁止访问"),
	NOT_FOUND(404, "未找到该资源，请检查路径是否正确"),
	METHOD_NOT_ALLOWED(405, "方法未允许"),
	NOT_ACCEPTABLE(406, "无法访问"),
	PROXY_AUTHENTICATION_REQUIRED(407, "需要代理服务器认证"),
	REQUEST_TIME_OUT(408, "请求超时"),
	CONFLICT(409, "冲突"),
	GONE(410, "资源已经不存在"),
	LENGTH_REQUIRED(411, "需要数据长度"),
	PRECONDITION_FAILED(412, "先决条件错误"),
	PAYLOAD_TOO_LARGE(413, "有效负载过大"),
	@Deprecated
	REQUEST_ENTITY_TOO_LARGE(413, "请求体过大"),
	URI_TOO_LONG(414, "URI过长"),
	@Deprecated
	REQUEST_URI_TOO_LONG(414, "请求URI过长"),
	UNSUPPORTED_MEDIA_TYPE(415, "不支持的媒体格式"),
	REQUESTED_RANGE_NOT_SATISFIABLE(416, "请求范围无法满足"),
	EXPECTATION_FAILED(417, "期望失败"),
	I_AM_A_TEAPOT(418, "拒绝冲咖啡，因为我是一个茶壶"),
	@Deprecated
	INSUFFICIENT_SPACE_ON_RESOURCE(419, "资源空间不足"),
	@Deprecated
	METHOD_FAILURE(420, "方法失败"),
	@Deprecated
	DESTINATION_LOCKED(421, "目标已锁定"),
	UNPROCESSABLE_ENTITY(422, "不可处理实体"),
	LOCKED(423, "已锁定"),
	FAILED_DEPENDENCY(424, "依赖失败"),
	TOO_EARLY(425, "太早了"),
	UPGRADE_REQUIRED(426, "需要升级"),
	PRECONDITION_REQUIRED(428, "前提条件"),
	TOO_MANY_REQUESTS(429, "请求过多"),
	REQUEST_HEADER_FIELDS_TOO_LARGE(431, "请求标头字段太大"),
	UNAVAILABLE_FOR_LEGAL_REASONS(451, "由于法律原因而无法使用"),

	INTERNAL_SERVER_ERROR(500, "服务器内部错误"),
	NOT_IMPLEMENTED(501, "未实现"),
	BAD_GATEWAY(502, "错误的网关"),
	SERVICE_UNAVAILABLE(503, "服务器正忙，请稍后再试"),
	GATEWAY_TIME_OUT(504, "网关超时"),
	HTTP_VERSION_NOT_SUPPORTED(505, "不支持的 HTTP 版本"),
	VARIANT_ALSO_NEGOTIATES(506, "变体也可协商"),
	INSUFFICIENT_STORAGE(507, "存储空间不足"),
	LOOP_DETECTED(508, "检测到循环"),
	BANDWIDTH_LIMIT_EXCEEDED(509, "超出带宽限制"),
	NOT_EXTENDED(510, "不扩展"),
	NETWORK_AUTHENTICATION_REQUIRED(511, "需要网络验证"),

	// 自定义：
	UNKNOWN_ERROR(-1, "未知错误");

	/**
	 * 状态码
	 */
	private final Integer code;

	/**
	 * 描述
	 */
	private final String message;

	HttpStatusEnum(Integer code, String message) {
		this.code = code;
		this.message = message;
	}

	/**
	 * 根据code获取HttpStatusEnum
	 */
	@Nullable
	public static HttpStatusEnum getHttpStatusEnumByCode(Integer code) {
		if (code == null) {
			return null;
		}
		return Arrays.stream(HttpStatusEnum.values()).filter(httpStatusEnum -> httpStatusEnum.code.equals(code)).findFirst().orElse(null);
	}

	/**
	 * 根据code获取message
	 */
	@Nullable
	public static String getMessageByCode(Integer code) {
		if (code == null) {
			return null;
		}
		HttpStatusEnum httpStatusEnum = getHttpStatusEnumByCode(code);
		return httpStatusEnum == null ? null : httpStatusEnum.message;
	}

	/**
	 * 从HttpServletRequest对象获取HttpStatus
	 */
	@Nullable
	public static HttpStatusEnum getStatus(HttpServletRequest request) {
		if (request == null) {
			return null;
		}
		Integer statusCode = (Integer) request.getAttribute(RequestDispatcher.ERROR_STATUS_CODE);
		if (statusCode == null) {
			return null;
		}
		try {
			return HttpStatusEnum.getHttpStatusEnumByCode(statusCode);
		} catch (Exception e) {
			log.error("获取HttpStatus发生异常", e);
			return null;
		}
	}

	public static class ExceptionMessage {

		public static final String NULL_POINTER_EXCEPTION = "空指针异常";
		public static final String CLASS_CAST_EXCEPTION = "类型转换异常";
		public static final String ARRAY_INDEX_OUT_OF_BOUNDS_EXCEPTION = "数组越界异常";
		public static final String INDEX_OUT_OF_BOUNDS_EXCEPTION = "下标越界异常";

	}

}
